﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using FisheryPlatform.Entity;
using System.Web;
using FisheryPlatform.Common;
using System.Configuration;
using System.Data.SqlClient;
using FisheryPlatform.DataAccess.DBUtility;
using System.Data;
using FisheryPlatform.SiteConfig;

namespace FisheryPlatform.DataAccess
{
    public class ExceptionMessageDB
    {
        /// <summary>
        /// 缓冲数量
        /// </summary>
        private static int BufferNum = 1;
        static System.Collections.Queue errorQue = new Queue();
        /// <summary>
        /// 根据异常数量会有如下3中处理情况：
        /// 1. 当异常数量小于缓冲值会缓存在服务器内存
        /// 2. 当异常数量达到设定缓冲值后即将缓存的异常都写入数据库
        /// 3. 当异常数量超过缓冲值则开始抛弃异常（在处理第二种情况的时候并发第三种情况，则会处理部分第三种情况的异常写入数据库）
        /// </summary>
        /// <param name="vEntity"></param>
        public static void Record(Exception ex)
        {
            #region
            HttpRequest Request = HttpContext.Current.Request;
            ExceptionEntity vEntity = new ExceptionEntity();
            vEntity.ThrowTime = DateTime.Now.ToString();
            vEntity.ExMessage = ex.Message;
            vEntity.ExDetail = ex.ToString();

            if (Request != null)
            {
                vEntity.ServerIP = Request.ServerVariables.Get("Local_Addr").ToString();
                vEntity.ClientIP = IPAddressUtility.GetClientIpFrom(Request);
                vEntity.SiteName = Request.Url.Host;
                vEntity.RequestUrl = Request.Url.ToString();

                if (Request.UrlReferrer != null)
                    vEntity.UrlReferrer = Request.UrlReferrer.ToString();
            }
            else
            {
                vEntity.ServerIP = System.Net.Dns.GetHostName();
                vEntity.ClientIP = System.Net.Dns.GetHostName();
                vEntity.SiteName = "非Web站点产生";
                vEntity.RequestUrl = "无";
                vEntity.UrlReferrer = "无";
            }
            if (errorQue.Count < BufferNum)
            {
                errorQue.Enqueue(vEntity);
            }
            #endregion

            if (errorQue.Count == BufferNum)
            {
                #region
                IList<ExceptionEntity> entityList = new List<ExceptionEntity>();
                for (int i = 0; i < BufferNum; i++)
                {
                    entityList.Add((ExceptionEntity)errorQue.Dequeue());
                }
                ExceptionMessageWorker exectionDB = new ExceptionMessageWorker(entityList);
                Thread thread = new Thread(new ThreadStart(exectionDB.SaveToDB));
                thread.Start();
                #endregion
            }
        }
    }

    public class ExceptionMessageWorker
    {
        #region
        private static Hashtable parmExceptionCache = Hashtable.Synchronized(new Hashtable());
        private static readonly string DBConnString = SiteConfigManager.DatabaseSettings["ExceptionDBConnString"].ConnectionString;
        IList<ExceptionEntity> exceptionEntitys = null;
        public ExceptionMessageWorker(IList<ExceptionEntity> vEntity)
        {
            exceptionEntitys = vEntity;
        }

        public void SaveToDB()
        {
            using (SqlConnection conn = new SqlConnection(DBConnString))
            {
                #region
                conn.Open();

                foreach (ExceptionEntity exceptionEntity in exceptionEntitys)
                {
                    SqlParameter[] parmList = new SqlParameter[]{
                            new SqlParameter("@ClientIP",SqlDbType.VarChar,30),
                            new SqlParameter("@ServerIP",SqlDbType.VarChar,30),
                            new SqlParameter("@ThrowTime",SqlDbType.VarChar,50),
                            new SqlParameter("@RequestUrl",SqlDbType.VarChar,400),
                            new SqlParameter("@UrlReferrer",SqlDbType.VarChar,400),
                            new SqlParameter("@ExMessage",SqlDbType.VarChar,800),
                            new SqlParameter("@ExDetail",SqlDbType.Text),
                            new SqlParameter("@SiteName",SqlDbType.VarChar,40)
                        };

                    parmList[0].Value = exceptionEntity.ClientIP;
                    parmList[1].Value = exceptionEntity.ServerIP;
                    parmList[2].Value = exceptionEntity.ThrowTime;
                    parmList[3].Value = exceptionEntity.RequestUrl;
                    parmList[4].Value = exceptionEntity.UrlReferrer;
                    parmList[5].Value = exceptionEntity.ExMessage;
                    parmList[6].Value = exceptionEntity.ExDetail;
                    parmList[7].Value = exceptionEntity.SiteName;

                    SqlCommand comm = conn.CreateCommand();
                    comm.Parameters.Clear();
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandText = "ExceptionInfo_Insert";
                    foreach (SqlParameter parm in parmList)
                        comm.Parameters.Add(parm);

                    comm.ExecuteNonQuery();
                }
                conn.Close();
                #endregion
            }
        }
        #endregion
    }
}
